package com.yc.http.tomcat.impl;

import com.yc.http.tomcat.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class TomcatImpl implements Tomcat {

    private String webroot = "E:\\gitee\\ycdemo\\C0-S2-Ply-demo\\WebContent\\WEB案例模板\\网站原型\\博客\\老王的个人博客(6.5)";

    // 单列集合   List, set,
    // 双列集合
    // Servlet 容器
    private Map<String, HttpServlet> servletMap = new HashMap<>();

    { // 块 ==》没有名字的构造函数
        // servlet 容器会读取到每个servlet地址，添加到容器
        servletMap.put("/hello.do", new HelloServlet());
        servletMap.put("/cookie.do", new CookieServlet());
        servletMap.put("/session.do", new SessionServlet());
        servletMap.put("/redirect.do", new RedirectServlet());
    }

    public static void main(String[] args) {
        new TomcatImpl().start(8080);
    }

    @Override
    public void start(int port) {
        ServerSocket server = null;
        System.out.println("启动服务器：" + port);
        try {
            server = new ServerSocket(port);
            while (true) {
                Socket socket = server.accept();
                // 構建請求和响应对象
                HttpServletRequest httpServletRequest = buildRequest(socket);
                HttpServletResponse httpServletResponse = buildResponse(socket, httpServletRequest);
                System.out.println(httpServletRequest);

                if (isServletRequest(httpServletRequest)) {
                    // servlet
                    String uri = getURI(httpServletRequest);
                    HttpServlet servlet = servletMap.get(uri);
                    try {
                        // service 分发请求
                        servlet.service(httpServletRequest, httpServletResponse);

                        //获取会话对象
                        HttpSession session = httpServletRequest.getSession();
                        // 获取会话id\
                        String id = session.getId();
                        // 写入cookie
                        Cookie cookie = new CookieImpl("JSESSIONID", id);
                        // 不能设置有效期
                        httpServletResponse.addCookie(cookie);

                        // 将数据推送到浏览器
                        httpServletResponse.flushBuffer();
                    } catch (ServletException e) {
                        throw new RuntimeException(e);
                    }

                } else if (isStaticRequest(httpServletRequest)) {
                    // 处理静态请求
                    processStaticRequest(httpServletRequest, httpServletResponse);
                } else {
                    // 404 错误
                    // 作业： 返回 404 页面
                    PrintWriter writer = httpServletResponse.getWriter();
                    httpServletResponse.setContentType("text/html;charset=utf-8");
                    httpServletResponse.setStatus(404, "Not Found");
                    writer.append("目标资源不存在:" + httpServletRequest.getRequestURI());
                    httpServletResponse.flushBuffer();
                }


                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public HttpServletRequest buildRequest(Socket socket) {
        try {
            return new HttpServletRequestImpl(socket);
        } catch (IOException e) {
            // 异常转型 ==> 异常链
            throw new RuntimeException(e);
        }
    }

    @Override
    public HttpServletResponse buildResponse(Socket socket, HttpServletRequest request) {
        try {
            return new HttpServletResponseImpl(socket);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String getURI(HttpServletRequest request) {
        String uri = request.getRequestURI();
        if (uri != null && uri.indexOf("?") > 0) {
            uri = uri.substring(0, uri.indexOf("?"));
        }
        return uri;
    }

    @Override
    public boolean isStaticRequest(HttpServletRequest request) {
        // 如果是非法的请求, uri为null 终止处理
        if (request.getRequestURI() == null) {
            return false;
        }
        String filepath = webroot + request.getRequestURI();
        // 截取 ？ 前面的路径
        if (filepath.indexOf("?") > 0) {
            filepath = filepath.substring(0, filepath.indexOf("?"));
        }
        // 物理文件存在， 那么是静态请求
        return new File(filepath).exists();
    }

    @Override
    public boolean isServletRequest(HttpServletRequest request) {
        // 请求路径在 servlet 容器中 ， 就是servlet 请求
        String uri = getURI(request);
        return servletMap.containsKey(uri);
    }

    @Override
    public boolean processStaticRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取响应输出流
        OutputStream out = response.getOutputStream();

        out.write("HTTP/1.1 200 OK\n".getBytes());
        String contentType = getMimeType(request.getRequestURI());
        out.write(("Content-Type: " + contentType + "\n").getBytes());
        out.write("\n".getBytes());
        //out.write("<h1>Hello world</h1>".getBytes());
        // 根据请求地址， 构建本地文件路径
        // /index.html ==》 c:/tomcat/webapps/a/index.html
        // webroot = c:/tomcat/webapps/a + /index.html
        String filepath = webroot + request.getRequestURI();
        // 截取 ？ 前面的路径
        if (filepath.indexOf("?") > 0) {
            filepath = filepath.substring(0, filepath.indexOf("?"));
        }
        try (FileInputStream fis = new FileInputStream(filepath)) {
            byte[] bytes = new byte[1024];
            int count;
            while ((count = fis.read(bytes)) > 0) {
                out.write(bytes, 0, count);
            }
        }
        return true;
    }

    @Override
    public boolean processServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        return false;
    }


    Map<String, String> mimeMap = new HashMap<>();
    {
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(
                    new File("E:\\软件\\教学\\apache-tomcat-8.0.45\\apache-tomcat-8.0.45\\conf/web.xml"));
            // 获取根节点
            Element root = doc.getRootElement();
            // 获取元素迭代器
            Iterator<Element> elementIterator = root.elementIterator("mime-mapping");
            while (elementIterator.hasNext()){
                // 获取下一个元素
                Element element = elementIterator.next();
                Element extension = element.element("extension");
                Element mimeType = element.element("mime-type");
                String ext = extension.getText();
                String mim = mimeType.getText();
                mimeMap.put(ext, mim);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public String getMimeType(String path) {
//        if (path.endsWith(".css")) {
//            return "text/css";
//        } else if (path.endsWith(".js")) {
//            return "application/x-javascript";
//        } else {
//            return "text/html;charset=utf-8";
//        }
        String ext = path.replaceAll(".+\\.(\\w+)", "$1");
        String mimeType = mimeMap.get(ext);
        return mimeType;
    }

    @Override
    public HttpServlet getServlet(HttpServletRequest request) {
        return null;
    }

    @Override
    public void createSession(HttpServletRequest request, HttpServletResponse response) {

    }

    @Override
    public void stop() {

    }
}
